﻿#if UNITY_EDITOR
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Text;
using UnityEditor;
using UnityEngine;
using UnityEngine.UI;
/// <summary>
/// Project逻辑代码【生成CopyToRuntime代码】
/// </summary>
public partial class ESF_Logic
{
    #region BuildSimulateBehaviour 生成SimulateBehaviour代码
    /// <summary>
    /// 生成SimulateBehaviour
    /// </summary>
    /// <returns>true:成功,false:失败</returns>
    [ESF_OneKeyBuild(ESF_enOneKeyBuildStep.BuildSimulateBehaviour)]
    [ESF_ProjectQuickButton("{0} {1}", ESF_enGUIDisplayWord.Build, ESF_enGUIDisplayWord.SimulateBehaviour)]
    public static bool BuildSimulateBehaviour()
    {
        bool result = true;
        if (projectSetting.xml.copyToXs != null)
        {
            string classNameISimulateBehaviour = "ISimulateBehaviour";
            //接口方法组
            Dictionary<int, ESF_SimulateBehaviourMethod> methods = new Dictionary<int, ESF_SimulateBehaviourMethod>();
            Dictionary<int, ESF_SimulateBehaviourMethod> mb= OnBuildSimulateBehaviourScripts(typeof(ESF_SimulateMonoBehaviour_Templete), enESF_SimulateBehaviourClassify.MonoBehaviour);
            Dictionary<int, ESF_SimulateBehaviourMethod> ub = OnBuildSimulateBehaviourScripts(typeof(ESF_SimulateUIBehaviour_Templete), enESF_SimulateBehaviourClassify.UIBehaviour);

            #region 统计Mono接口
            foreach (var key in mb)
            {
                if (!methods.ContainsKey(key.Key))
                {
                    methods.Add(key.Key, key.Value);
                }
            }
            #endregion

            #region 统计UI接口
            foreach (var key in ub)
            {
                if (!methods.ContainsKey(key.Key))
                {
                    methods.Add(key.Key, key.Value);
                }
            }
            #endregion
                        
            float progress = 0;
            int count = 0;
            string className = string.Empty;
            string directory = string.Empty;
            string path = string.Empty;
            string code = string.Empty;

            #region 生成Behaviour组件    
            EditorUtility.ClearProgressBar();
            List<enESF_SimulateBehaviourClassify> enums = typeof(enESF_SimulateBehaviourClassify).ESF_ToEnum<enESF_SimulateBehaviourClassify>();
            foreach (var key in enums)
            {
                directory = Path.Combine(projectSetting.xml.simulateBehaviourRootFolder, key.ToString());
                ESF_Utility.DeleteFolder(directory);
                if (!Directory.Exists(directory))
                {
                    Directory.CreateDirectory(directory);
                }
            }            
            progress = 0;
            count = methods.Count;            
            foreach (var key in methods)
            {
                directory = Path.Combine(projectSetting.xml.simulateBehaviourRootFolder, key.Value.simulateBehaviourClassify.ToString());
                path = ESF_Utility.GetPath(key.Value.className, directory, enESF_UnityFileExt.CS);
                switch (key.Value.simulateBehaviourClassify)
                {
                    case enESF_SimulateBehaviourClassify.MonoBehaviour:
                        code = File.ReadAllText(ESF_enResxTempleteFile.Compiler_Simulate_MonoBehaviour_Templete_txt);
                        break;
                    case enESF_SimulateBehaviourClassify.UIBehaviour:
                        code = File.ReadAllText(ESF_enResxTempleteFile.Compiler_Simulate_UIBehaviour_Templete_txt);
                        break;
                }

                code = code.CompilerCSharp(new
                {
                    met = key.Value,
                });
                File.WriteAllText(path, code);
                progress++;
                EditorUtility.DisplayProgressBar($"Build Simulate{key.Value.simulateBehaviourClassify}", key.Value.className, progress / count);
            }
            ESF_P.ESF_Step($"Build SimulateBehaviour =>{count}");
            #endregion
            
            #region 生成ISimulateBehaviour脚本
            path = ESF_Utility.GetPath(classNameISimulateBehaviour, projectSetting.xml.simulateBehaviourRootFolder, enESF_UnityFileExt.CS);
            code = File.ReadAllText(ESF_enResxTempleteFile.Compiler_Simulate_IBindSimulateBehaviour_Templete_txt);
            EditorUtility.DisplayProgressBar("Build ISimulateBehaviour", classNameISimulateBehaviour, 0);            
            code = code.CompilerCSharp(new {
                mets = methods,
                clsName = classNameISimulateBehaviour
            });
            File.WriteAllText(path, code);
            EditorUtility.DisplayProgressBar("Build ISimulateBehaviour", classNameISimulateBehaviour, 1);
            ESF_Utility.ExecuteMenuAssetsRefresh();
            #endregion

            #region 生成ISimulateBehaviour方法接口实现脚本       
            className = $"AbsESF_SimulateBehaviour_{classNameISimulateBehaviour}";
            path = ESF_Utility.GetPath(className, Path.Combine(projectSetting.xml.GetSimulateBehaviourEnumCopyToHFSrcFolder(), "Simulate"), enESF_UnityFileExt.CS);
            code = File.ReadAllText(ESF_enResxTempleteFile.Compiler_Simulate_AbsESF_SimulateBehaviour_IESF_SimulateBehaviour_Templete_txt);
            EditorUtility.DisplayProgressBar($"Build {className}", className, 0);
            code = code.CompilerCSharp(new
            {
                mets = methods,
            });
            FileInfo file = new FileInfo(path);
            if (!file.Exists) {
                Directory.CreateDirectory(file.Directory.FullName);
            }
            File.WriteAllText(path, code);
            EditorUtility.DisplayProgressBar($"Build {className}", className, 1);
            #endregion

            #region 创建模拟Behaviour事件枚举
            string eventEnumName = projectSetting.xml.GetSimulateBehaviourEnumName();
            EditorUtility.DisplayProgressBar("Build SimulateBehaviourEventEnum", eventEnumName, 0);
            code = File.ReadAllText(ESF_enResxTempleteFile.Compiler_Simulate_BehaviourEnum_Templete_txt);
            code = code.CompilerCSharp(new
            {
                enName = eventEnumName,
                mets = methods
            });
            directory = Path.Combine(projectSetting.xml.GetSimulateBehaviourEnumCopyToHFSrcFolder(), "Enums");
            if (!Directory.Exists(directory))
            {
                Directory.CreateDirectory(directory);
            }
            path = ESF_Utility.GetPath(eventEnumName, directory, enESF_UnityFileExt.CS);
            File.WriteAllText(path, code);
            EditorUtility.DisplayProgressBar("Build SimulateBehaviourEventEnum", eventEnumName, 1);
            #endregion

            #region 生成绑定事件组件映射
            className = "ESF_SimulateBehaviour_BindEventComponentMap";
            EditorUtility.DisplayProgressBar("Build SimulateBehaviourBindEventComponentMap", className, 0);
            code = File.ReadAllText(ESF_enResxTempleteFile.Compiler_Simulate_BindEventComMap_Templete_txt);
            code = code.CompilerCSharp(new
            {
                mets = methods,
            });
            directory = Path.Combine(projectSetting.xml.GetSimulateBehaviourEnumCopyToHFSrcFolder(), "Simulate");
            if (!Directory.Exists(directory))
            {
                Directory.CreateDirectory(directory);
            }
            path = ESF_Utility.GetPath(className, directory, enESF_UnityFileExt.CS);
            File.WriteAllText(path, code);
            EditorUtility.DisplayProgressBar("Build SimulateBehaviourBindEventComponentMap", className, 1);
            #endregion
            
            ESF_Utility.ExecuteMenuAssetsRefresh();
            EditorUtility.ClearProgressBar();
        }        
        ESF_P.ESF_Log($"BuildSimulateBehaviour Success.");
        return result;
    }

    /// <summary>
    /// 生成模拟Behaviour脚本
    /// </summary>
    /// <param name="_typeTemplete">类型模板</param>
    /// <param name="_typeClassify">类型分类</param>
    static Dictionary<int, ESF_SimulateBehaviourMethod> OnBuildSimulateBehaviourScripts(Type _typeTemplete, enESF_SimulateBehaviourClassify _typeClassify)
    {
        Dictionary<int, ESF_SimulateBehaviourMethod> result = new Dictionary<int, ESF_SimulateBehaviourMethod>();
        MethodInfo[] methods = _typeTemplete.GetMethods(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.DeclaredOnly);        
        if (methods != null && methods.Length > 0)
        {
            ESF_SimulateBehaviourMethod ti = null;
            foreach (MethodInfo m in methods)
            {
                ti = new ESF_SimulateBehaviourMethod(m, _typeClassify);
                if (result.ContainsKey(ti.simulateNameKey))
                {
                    ESF_P.ESF_Error($"Method 【{m.Name} ({ti.methodFormalParameters.ESF_Join(enESF_SeparatorSymbol.Comma)})】is exists.");
                }
                else
                {
                    result.Add(ti.simulateNameKey, ti);
                }                
            }
        }        
        return result;
    }
    #endregion
}
#endif
